
#import <stdio.h>

#import "pmt_time_utils.h"

#import "PMTStandardAllocator.h"
#import "PMTStandardAllocatorTest.h"
#import "PMTStopWatch.h"
#import "PMTTesting.h"

static BOOL test_alloc();

double test_speed_alloc(const size_t size, const BOOL zero_out);

void pmt_unit_test_standard_allocator()
{
    printf("[ StandardAllocator ]\n");
    printf("alloc: %s\n", test_alloc() ? "pass" : "FAIL");
}

void pmt_perf_test_standard_allocator()
{
    printf("[ StandardAllocator ]\n");
    printf("alloc (size=10, !zero): %f\n", test_speed_alloc(10,NO));
    printf("alloc (size=10, zero): %f\n", test_speed_alloc(10,YES));
    printf("alloc (size=100, !zero): %f\n", test_speed_alloc(100,NO));
    printf("alloc (size=100, zero): %f\n", test_speed_alloc(100,YES));
}

static BOOL test_alloc()
{
    PMTStandardAllocator* allocator = [[PMTStandardAllocator alloc] init];
    for(size_t ii = 1; ii <= 1000; ++ii) {
        id alloced = [allocator alloc:ii zeroOut:YES];
        if( alloced == 0 ) {
            return NO;
        }
        char* chars = (char*)alloced;
        for(size_t jj = 0; jj < ii; ++jj) {
            if( chars[jj] != 0 ) {
                return NO;
            }
        }
    }
    [allocator release];
    return YES;
}

//static BOOL test_release()

double test_speed_alloc(const size_t size, const BOOL zero_out)
{
    const size_t iters = 100000;
    const size_t count = 1000;
    double total = 0;
    struct timeval elapsed;
    PMTStandardAllocator* allocator = [[PMTStandardAllocator alloc] init];
    PMTStopWatch* stopwatch = [[PMTStopWatch alloc] init];

    for(unsigned iter = 0; iter != iters; ++iter)
    {
        id alloced[count];
        [stopwatch start];
        for(unsigned ii = 0; ii != count; ++ii) {
            alloced[ii] = [allocator alloc:size zeroOut:zero_out];
        }
        [stopwatch stop];
        for(unsigned ii = 0; ii != count; ++ii)
        {
            [allocator release:alloced[ii]];
        }
    }
    [stopwatch elapsed:&elapsed];
    total = pmt_timeval_to_micros(&elapsed);
    return pmt_testing_calc_nanos_per(total, (unsigned)iters, (unsigned)count);
}



